#pragma once

#include "database/connection_pool.h"
#include <string>
#include <vector>

namespace cpp_backend
{
    namespace database
    {

        /**
         * @brief Redis连接
         */
        class RedisConnection : public IConnection
        {
        public:
            RedisConnection(const std::string &host, int port, const std::string &password = "");
            ~RedisConnection() override;

            bool IsValid() const override;
            bool Ping() override;
            void Close() override;
            bool Reconnect() override;

            // Redis命令接口
            bool Set(const std::string &key, const std::string &value, int expire_seconds = 0);
            bool Get(const std::string &key, std::string &value);
            bool Del(const std::string &key);
            bool Exists(const std::string &key);
            bool Expire(const std::string &key, int seconds);
            // 计数操作
            bool Incr(const std::string &key, long long &out_value);
            bool IncrBy(const std::string &key, long long delta, long long &out_value);

            // 列表操作
            bool LPush(const std::string &key, const std::string &value);
            bool RPush(const std::string &key, const std::string &value);
            bool LPop(const std::string &key, std::string &value);
            bool RPop(const std::string &key, std::string &value);

            // 集合操作
            bool SAdd(const std::string &key, const std::string &member);
            bool SRem(const std::string &key, const std::string &member);
            bool SIsMember(const std::string &key, const std::string &member);

            // 哈希操作
            bool HSet(const std::string &key, const std::string &field, const std::string &value);
            bool HGet(const std::string &key, const std::string &field, std::string &value);
            bool HDel(const std::string &key, const std::string &field);

            // 服务器信息
            bool GetInfo(std::string &info_output);

        private:
            std::string host_;
            int port_;
            std::string password_;
            void *context_; // hiredis context
        };

        /**
         * @brief Redis连接池
         */
        class RedisPool : public ConnectionPool<RedisConnection>
        {
        public:
            /**
             * @brief 获取单例实例
             */
            static RedisPool &Instance();

            /**
             * @brief 构造Redis连接池
             * @param host Redis服务器地址
             * @param port Redis服务器端口
             * @param password 密码（可选）
             * @param min_size 最小连接数
             * @param max_size 最大连接数
             */
            RedisPool(const std::string &host = "127.0.0.1",
                      int port = 6379,
                      const std::string &password = "",
                      size_t min_size = 5,
                      size_t max_size = 20);

            ~RedisPool() override = default;

        protected:
            ConnectionPtr CreateConnection() override;

        private:
            std::string host_;
            int port_;
            std::string password_;
        };

        /**
         * @brief RAII风格的Redis连接管理器
         *
         * 自动获取和归还连接
         */
        class RedisConnectionGuard
        {
        public:
            explicit RedisConnectionGuard(RedisPool &pool, int timeout_ms = 3000)
                : pool_(pool), conn_(pool.AcquireConnection()) {}

            ~RedisConnectionGuard()
            {
                if (conn_)
                {
                    pool_.ReleaseConnection(conn_);
                }
            }

            RedisConnection *operator->()
            {
                return conn_.get();
            }

            RedisConnection *Get()
            {
                return conn_.get();
            }

            bool IsValid() const
            {
                return conn_ && conn_->IsValid();
            }

        private:
            RedisPool &pool_;
            std::shared_ptr<RedisConnection> conn_;
        };

    } // namespace database
} // namespace file_server
